/*
 ============================================================================
 Name        : main.cpp
 Author      : Ahmed K. Atwa
 Version     : 0.1
 Copyright   : MS-PL
 Description : Entry point for parsa
 ============================================================================
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include "commonDefs.h"
#include "commonCPU.h"
#include "commonCuda.cu"
#include "PlanWrapper.cu"
/*
This program benchmarks different parallel suffix array construction algorithms.
inputs (arguments):
1. -file-input=<name of the text file that contains row text>. Note that, we 
only support file sizes that are fully loadable in memory i.e. we will not do
any external memory computations.
2. -plan=<planName>: this selects which plan/algorithm to use for the given problem.
3. -output=<out.txt> : for the output file containing the suffix array index.
4. -arguments= other arguments to be passed to the specific algorithms in a single argument
ex. -useGPU=true-useQuickRadixSort=true and so on. Note that, it has to be tokenizable by '-'
*/
int
main(int argc, char* argv[])
{
	/* free variables */
    int i = 0; 
    char* pFileName = NULL,
          *pOutputFile = NULL,
		  *pPlanName = NULL;
	char *pInputContents = NULL;
    char** ppOtherArguments = NULL;
	int * pSAOutput = NULL;

    /*Initialize Parsa */
    printf("Initializing parsa CPU and GPU compute nodes\n");
    printf("Ahmed K. Atwa Mohamed\n");
    printf("initializing CUDA\n");
	ASSERT ((true==InitCUDA()),"Failed to initialize CUDA");
	//CUT_DEVICE_INIT(1,0);    
    /* Parse arguments */
    for (i = 1; i < argc; i++)
    {
        char* pArg = argv[i];
        if ('-'== pArg[0])
        {
            if (0 == strncmp(pArg,"-file-input=",strlen("-file-input=")))
            {
                pFileName = pArg+strlen("-file-input=");
				ASSERT((NULL!= pFileName && 0 != *pFileName),"invalid filename!\n");
            }
            else if (0 == strncmp(pArg,"-output=",strlen("-output=")))
            {
                pOutputFile = pArg+strlen("-output=");
				ASSERT((NULL!= pOutputFile && 0 != *pOutputFile),"invalid output filename!\n");
            }
            else if (0 == strncmp(pArg,"-plan=",strlen("-plan=")))
            {
                pPlanName = pArg+strlen("-plan=");
				ASSERT((NULL!= pPlanName && 0 != *pPlanName),"invalid plan name!\n");
            }
            else
            {
                ppOtherArguments = argv+i;
            }
        } 
        else
        {
			printf("ERROR: invalid argument!\n");
        }
    }
	ASSERT ((NULL != pFileName && NULL != pOutputFile && NULL != pPlanName),"missing input parameters! \n");
    /* load inputs */
	int fileSize = loadFile(pFileName, &pInputContents);
	ASSERT( (0 < fileSize && NULL != pInputContents), "unable to read file \n");
    
	constructSA_PlanT* pfnOptimalPlan = selectPlan(pPlanName);
    /* initialize counters*/
#ifdef USE_CUDA_TIMER
	ASSERT(initilizaAndStartTimeCounter(),"failed to initialize counters \n");
#else
	CStopWatch timer;
	timer.startTimer();	
#endif
	/* execute the plan */
	pfnOptimalPlan(pInputContents, fileSize, &pSAOutput,*ppOtherArguments);
	/* stop counters */
#ifdef USE_CUDA_TIMER
	ASSERT(stopTimeCounter(),"failed to stop counters \n");
	printf("execution time = %i ms",getTimerValueInMS());
	ASSERT(killTimeCounter(),"failed to kill counters \n");
#else
	timer.stopTimer();
	printf("execution time = %f ms",timer.getElapsedTime());
#endif
    /* output results */
	saveFile(pOutputFile,&pSAOutput,fileSize);
exit:
	/* free memory */
	printf("\nexiting: Free memory\n");
	if( NULL != pInputContents)
	{
		delete pInputContents;
		pInputContents = NULL;
	}
	if (NULL != pSAOutput)
	{
		delete pSAOutput;
		pSAOutput = NULL;
	}
    return EXIT_SUCCESS;
}
